#include "npc2.h"
#include "../effect.h"
#include "path.h"
#include "../bullet.h"
#include "../gun/gun.h"
#include "../common.h"
#include "../player.h"

namespace fireplane{
	NPC2::NPC2(EnemyType type):
		Enemy(type),_fire_tick(0),
		_fire_middle_gun_tick(0),
		_is_deading(false),
		_state(e_npc2_normal)
	{}

	bool NPC2::updateState( float dt ){
		bool ret = true;

		if (isDestroy())
		{
			return false;
		}

		if (_is_attak){
			_attack_back_time += dt;
			if (_attack_back_time > 0.5f){
				_attack_back_time = 0;
				_is_attak = false;
				_sprite->setColor(ccc3(255,255,255));
			}
		}
		
		doNPCstate(dt);

		CCPoint pos = this->getPosition();
		if (pos.y < -50){
			ret =  false;
		}

		list<CCRect>::iterator it = _all_collision_rects.begin();
		for (;it != _all_collision_rects.end();it ++){
			CCRect& rect = (*it);
			rect.origin.x = pos.x - rect.size.width / 2;
			rect.origin.y = pos.y - rect.size.height / 2;
		}

		if(!_is_deading){
			_fire_tick += dt;

			_fire_middle_gun_tick += dt;
			if(_fire_middle_gun_tick > 3.0f){
				_fire_middle_gun_tick = 0;
				_gun->fire(Bullet::BI_img17);
			}
		 
			float op = _fire_tick * 255.0f / 3.0f;
			_fireEffect->setOpacity(op);

		}
		else{
			if(0 == _sprite->numberOfRunningActions()){
				setDestroyFlag(true);

				// create effect
				/*CCPoint worldpos = this->getPosition();
				worldpos = this->getParent()->convertToWorldSpace(worldpos);

				Effect::CreateNpc2Bomb cmd;
				cmd._id = Effect::ET_npc2;
				cmd.worldPos = worldpos;

				Effect::createEffect(&cmd);
				*/
			}
		
		}
		
		return ret;
	}

	NPC2::~NPC2(){}

	void NPC2::onInit(CreateArg* arg)
	{
		CreateNormalEnemy* targ = (CreateNormalEnemy*)arg;

		_sprite = CCSprite::create("enemy/npc2/0.png");
		addChild(_sprite);
		this->setPosition(targ->pos);
		CCSize contentsize = _sprite->getContentSize();

		CCActionInterval* action1 = Common::createFrameAnimation("enemy/npc2/",2,CCRectMake(0,0,contentsize.width,contentsize.height));
		action1->setDuration(0.2f);
		action1->setTag(e_npc2_normal);
		_sprite->runAction( CCRepeatForever::create((CCActionInterval*)action1));

		CCRect rect = CCRectMake(targ->pos.x - contentsize.width / 2,targ->pos.y - contentsize.height / 2,contentsize.width,
			contentsize.height);

		_all_collision_rects.push_back(rect);

		_hp = 400;
		_is_attak = false;
		_attack_back_time = 0;

		_total_step = 1000;
		_cur_step = 1;
		_speed = 200.0f;

		Gun::CreateNormalGun arg_npc2(Gun::GT_normal_gun);
		arg_npc2.tdir = ccp(0,-1);
		arg_npc2.tspeed = 300;
		arg_npc2.o = Bullet::BO_ENEMY;
		arg_npc2.pos = ccp(0,-75);

		_fireEffect = CCSprite::create("bullet/npc2/1.png");
		addChild(_fireEffect);
		_fireEffect->setPosition(arg_npc2.pos);
		_fireEffect->setOpacity(0);

		_gun = Gun::createGun(&arg_npc2);
		addChild(_gun);
		_gun->setBulletType(Bullet::BT_laser_bullet);
	}

	void NPC2::destroy()
	{
		Enemy::destroy();
	}

	void NPC2::onCollision2Player(){
		if(_is_deading){
			return;
		}

		_onAttack(-_hp);
	}

	void NPC2::_onAttack(int addHp){
		if(_is_deading){
			return;
		}

		_hp += addHp;
		if (_hp <= 0)
		{
			_hp = 0;
			_is_deading = true;
			_sprite->stopAllActions();

			// create effect
			CCPoint worldpos = this->getPosition();
			worldpos = this->getParent()->convertToWorldSpace(worldpos);

			Effect::CreateNpc2Bomb cmd;
			cmd._id = Effect::ET_npc2;
			cmd.worldPos = worldpos;
			
			Effect::createEffect(&cmd);

		}

		if(!_is_deading){
			_sprite->setColor(ccc3(180,0,0));
			_is_attak = true;
			_attack_back_time = 0;
		}
		/*
		else{
			CCPoint pos = _sprite->getPosition();
			_sprite->initWithFile("enemy/npc2/0.png");
			_sprite->setPosition(pos);

			pos.x += 10;
			pos.y -= 10;
			CCMoveTo* m0 = CCMoveTo::create(0.4f,pos);
			_sprite->runAction(m0);
			_sprite->runAction(CCScaleTo::create(0.4f,0.5f));
		}
		*/
	}

	void NPC2::onAttack()
	{
		if(_is_deading){
			return;
		}

		_onAttack(-10);
	}

	bool NPC2::initBezier(string npc_name ,CCPoint gen_pos)
	{
		//BezierList* data = Path::getPath()->getBezierList(npc_name);
		BezierList* data = Path::getPath()->getNPCPath(0,npc_name);

		if(data == NULL)
			return false;
		_bezier_list = new BezierList();
		list<Bezier*>::iterator it = data->begin();

		int idx = 0;
		CCPoint start_pos;
		for (;it != data->end();it ++)
		{
			Bezier* b = (*it);
			Bezier* n = new Bezier();
			for(int i = 0;i < e_bezier_point_max;i++){
				n->point[i] = b->point[i];

				if(idx == 0){
					start_pos = n->point[i];
				}

				n->point[i].x -= start_pos.x;
				n->point[i].y -= start_pos.y;

				n->point[i].x += gen_pos.x;
				n->point[i].y += gen_pos.y;

				idx ++;
			}

			_bezier_list->push_back(n);
		}

		_bezier_it = _bezier_list->begin();

		calcNextPos();

		return true;
	}
	void NPC2::calcNextPos(){
		Bezier *bezier = *_bezier_it;
		_next_pos = Path::getPath()->hornbez2(bezier->point,(float) _cur_step / (float)_total_step);
	}

	void NPC2::calcRoate(CCPoint lastPos)
	{
		CCPoint curpos = this->getPosition();
		CCPoint vector = ccpSub(curpos,lastPos);
		if(vector.equals(CCPointZero)){
			vector.setPoint(0,-1);
		}

		vector = ccpNormalize(vector);
		float degree = CC_RADIANS_TO_DEGREES(acos(ccpDot(vector,ccp(0,1))));

		if (ccpCross(vector,ccp(0,1)) < 0)
		{
			degree = 360 - degree;
		}

		degree += 180;
		this->setRotation(degree);
	}

	void NPC2::goBeizer(float dt)	
	{
		if( _bezier_it == _bezier_list->end())
			return;

		CCPoint lastPos = this->getPosition();

		Bezier *bezier = NULL;
		bool change = false;
		float move = _speed * dt;

		while(1){
			CCPoint pos = this->getPosition();
			CCPoint dir = ccpSub(_next_pos,pos);
			float dis = ccpLength(dir);

			change = false;
			float tmove = move;
			if(move > dis){
				move -= dis;
				tmove = dis;
				change = true;
			}

			dir = ccpNormalize(dir);

			CCPoint v_move = dir;
			v_move.x *= tmove;
			v_move.y *= tmove;

			pos.x += v_move.x;
			pos.y += v_move.y;

			this->setPosition(pos);
			if(change){
				_cur_step ++;
				if(_cur_step > _total_step){
					_bezier_it++;
					_cur_step = 1;
				}

				if( _bezier_it != _bezier_list->end()){
					calcNextPos();
				}
				else{
					break;
				}
			}
			else{
				break;
			}
		}

		calcRoate(lastPos);

	}

	float NPC2::getAngle(CCPoint ref_pos){
		CCPoint mypos = this->getPosition();
		mypos = this->getParent()->convertToWorldSpace(mypos);
		mypos = Player::getMainPlayer()->getPlayerParent()->convertToNodeSpace(mypos);

		_dir.x = ref_pos.x - mypos.x;
		_dir.y = ref_pos.y - mypos.y;

		_dir = ccpNormalize(_dir);

		CCPoint up(0,-1);
		float angle = ccpDot(_dir,up);
		angle = acos(angle);
		angle = angle * 180.0f/ 3.14f;
		angle = -angle;

		float s = ccpCross(_dir,up);
		if(s > 0){
			angle = 360 - angle;
		}

		return angle;
	}

	void NPC2::doNPCstate(float dt)
	{
		float move = 0.0f;
		CCPoint pos = this->getPosition();
		CCPoint pos_player = Player::getMainPlayer()->getPlayerPos();
		CCPoint dir = ccpSub(pos,pos_player);
		float dis = ccpLength(dir);

		switch (_state)
		{
		case e_npc2_normal:

			if(dis < 600)
			{	
				_state = e_npc2_standby;
			}
			else 
			{
				move= _speed * dt;
				pos.y -= move;
				this->setPosition(pos);
			}
			break;
		case e_npc2_standby:
			{
				CCMoveBy* m0 = CCMoveBy::create(0.1f,ccp(0,-5));
				CCMoveBy* m1 = CCMoveBy::create(0.1f,ccp(0,5));
				CCSequence* seq = CCSequence::create(m0,m1,NULL);
				CCRepeatForever* action1 = CCRepeatForever::create(seq);
				CCAction* action2 = (CCAction*)action1->copy();
				_sprite->runAction(action1);
				_fireEffect->runAction(action2);

				_state = e_npc2_aim;
				_total_angle = getAngle(Player::getMainPlayer()->getPlayerPos());
				_cur_angle   = getAngle(CCPointZero);
			}
			break;
		case e_npc2_aim:
			if(_cur_angle <= _total_angle)
				this->setRotation(_cur_angle++);
			else
				this->setRotation(getAngle(Player::getMainPlayer()->getPlayerPos()));

			_state = e_npc2_aim;
			break;
		default:break;
		}
	}


}